#ifndef COMMON_H
#define COMMON_H

#include <QApplication>
#include <QVector>
#include <QByteArray>
#include <QJsonObject>
#include <QJsonDocument>

#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
#include <windows.h>
#elif !defined(__unix)
#define __unix
#endif

#ifdef __unix
#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/types.h>
#endif

#define BUF_SIZE                       1024*4               // 最大文件发送大小
#define MAX_FILENAME                   256                  // 能发送的最大文件数量
#define SERIALPORT_BUF_SIZE            1024                 // 每次串口发送数据大小
#define IDD_TCP_VERSION                1000                 // tcp消息版本号
#define IDD_UDP_VERSION                1001                 // udp消息版本号
#define IDD_SERIALPORT_VERSION         2002                 // 串口消息版本号

/********************< 版本管理协议 >**********************************/
#define IDD_SVNVERION_USER                 5100             // 用户操作
#define IDD_SVNVERION_REGISTER_USER        5101             // 注册用户
#define IDD_SVNVERION_UPDATE_USER          5102             // 更新用户
#define IDD_SVNVERION_DELETE_USER          5103             // 删除用户
#define IDD_SVNVERION_LOGIN_USER           5104             // 用户登陆
#define IDD_SVNVERION_USER_SUC             5105             // 用户操作成功
#define IDD_SVNVERION_USER_FAIL            5106             // 用户操作失败
#define IDD_SVNVERION_REGISTER_USER_EXIST  5107             // 用户已经存在

#define IDD_SVNVERSION_PROJECT             5200             // 项目管理
#define IDD_SVNVERSION_PROJECT_ADD         5201             // 添加项目
#define IDD_SVNVERSION_PROJECT_DEL         5202             // 删除项目
#define IDD_SVNVERSION_VERSION_ADD         5203             // 添加版本
#define IDD_SVNVERSION_VERSION_DAT_ADD     5204             // 添加版本数据
#define IDD_SVNVERSION_VERSION_DAT_GET     5205             // 得到版本数据
#define IDD_SVNVERSION_PROJECT_INFO_GET    5206             // 得到指定项目的信息
#define IDD_SVNVERSION_PROJECT_SUC         5207             // 用户操作成功
#define IDD_SVNVERSION_PROJECT_FAIL        5208             // 用户操作失败
/********************************************************************/

//#define ENABLEREMOTEVOICE      1                // 是否启用remotevoice

/**
 * @brief The FileRecvError enum 文件接收错误返回
 */
enum FileRecvError
{
    STATE_CHECKNUM = 0,        // 文件校验码不对
    STATE_SIZE,                // 文件长度不对
    STATE_NOTWRITE,            // 路径不对，无法写入
    STATE_SUCCESS,             // 接收成功
    STATE_START,               // 开始接收
    STATE_NULL
};

/**
 * @brief The DB_Type enum 要连接的数据库类型
 */
enum DB_Type
{
    QMYSQL = 0,           // MYSQL
    QODBC,                // MSSQL
    QSQLITE,              // QSQLITE
    TYPE_NULL
};

/**
 * @brief 要发送udp报文头
 */
#pragma pack(push,1)
struct tagDatagramHearder
{
    int version;
    qint64 size;                   // 数据大小
};
#pragma pack(pop)

/**
 * @brief 要发送串口报文头
 */
#pragma pack(push,1)
struct tagPacketHearder
{
    int version;
    qint64 size;                   // 数据大小
};
#pragma pack(pop)

/**
 * @brief The tagFileStruct struct 要发送的文件结构
 */
#pragma pack(push,1)
struct tagFileStruct
{
    char mark[3];                  // 'F','I','L'
    char fileName[MAX_FILENAME];            // 文件所在相对路径
    qint64 srcfileSize;            // 原始文件大小
    qint64 compressfileSize;       // 压缩后文件大小
    quint16 checknum;              // 数据校验码
};
#pragma pack(pop)

/**
 * 要发送的数据结构
 */
#pragma pack(push,1)
struct tagDataStruct
{
    char mark[3];                  // 'D','A','T'
    qint64 srcdataSize;            // 原始数据大小
    qint64 compressdataSize;       // 压缩后数据大小
    quint16 checknum;              // 数据校验码
};
#pragma pack(pop)

/**
 * 用于版本操作
 */
#pragma pack(push,1)
struct tagVersionOper
{
    tagVersionOper()
        : tagIndex(0),versionid(0),userid(0)
    {
        memset(userpwd,0,sizeof(userpwd));
    }

    int tagIndex;
    int versionid;
    int userid;
    char userpwd[128];
};
#pragma pack(pop)

/**
 * @brief The tagSVNVersionFileStruct struct svn版本文件结构
 */
struct tagSVNVersionFileStruct
{
    char fileName[MAX_FILENAME];            // 文件所在相对路径
    int fileSize;                           // 文件大小
    int fileChanged;                        // 文件是否改变：0-没改变；1-改变了
};

/**
 * @brief The tagSVNVersionPathStruct struct svn版本工作目录结构
 */
struct tagSVNVersionPathStruct
{
    char tag[3];                            // 'S','V','N'
    int fileCount;                          // 文件数量
    int srcDataSize;               // 原始数据大小
};

/* get system time */
static inline void itimeofday(long *sec, long *usec)
{
#if defined(__unix)
    struct timeval time;
    gettimeofday(&time, NULL);
    if (sec) *sec = time.tv_sec;
    if (usec) *usec = time.tv_usec;
#else
    static long mode = 0, addsec = 0;
    BOOL retval;
    static long long freq = 1;
    long long qpc;
    if (mode == 0) {
        retval = QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
        freq = (freq == 0) ? 1 : freq;
        retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc);
        addsec = (long)time(NULL);
        addsec = addsec - (long)((qpc / freq) & 0x7fffffff);
        mode = 1;
    }
    retval = QueryPerformanceCounter((LARGE_INTEGER*)&qpc);
    retval = retval * 2;
    if (sec) *sec = (long)(qpc / freq) + addsec;
    if (usec) *usec = (long)((qpc % freq) * 1000000 / freq);
#endif
}

/* get clock in millisecond 64 */
static inline long long iclock64(void)
{
    long s, u;
    long long value;
    itimeofday(&s, &u);
    value = ((long long)s) * 1000 + (u / 1000);
    return value;
}

static inline unsigned int iclock()
{
    return (unsigned)(iclock64() & 0xfffffffful);
}

/// 加载本静态库的资源
void init_lib_resources(void);
/// 卸载本静态库的资源
void cleanup_lib_resources(void);
/// 生成日志文件
void init_log_file(QString filepath);
/// 保存源文件到目标文件(主要网络传输中使用)
bool sava_file(QString srcfile,QString decfile);
/// 初始化崩溃系统
void init_dump_system(void);
/// 拷贝文件
bool copyFileToPath(QString sourceDir ,QString toDir, bool coverFileIfExist);
/// 拷贝文件夹
bool copyDirectoryFiles(const QString &fromDir, const QString &toDir, bool coverFileIfExist);
/// 得到指定目录下所有的文件
int FindFile(const QString& _filePath,QVector<QString> &filelist);
/// QJsonObject转QString
QString JsonToString(const QJsonObject& json);
/// QString转QJsonObject
QJsonObject StringToJson(const QString& str);
/// 删除目录下所有文件和文件夹
bool removeFolderContent(const QString &folderDir);

#endif // COMMON_H
